package com.yanqu.road.server.manger.activity.stelesoul;

import com.yanqu.road.entity.activity.ActivityConfig;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.stelesoul.SteleSoulIndexData;
import com.yanqu.road.entity.activity.stelesoul.SteleSoulMapData;
import com.yanqu.road.entity.activity.stelesoul.SteleSoulParamData;
import com.yanqu.road.entity.activity.stelesoul.SteleSoulUserData;
import com.yanqu.road.entity.activity.stelesoul.config.*;
import com.yanqu.road.entity.enums.activity.stelesoul.eSteleSoulStateType;
import com.yanqu.road.entity.enums.eActivityType;
import com.yanqu.road.logic.bussiness.activity.SteleSoulBusiness;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.activity.stelesoul.SteleSoulModule;
import com.yanqu.road.server.manger.activity.NormalActivityMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;

import java.util.*;

public class SteleSoulMgr extends TempMgr {

    private static SteleSoulConfig steleSoulConfig;

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        return true;
    }

    @Override
    public boolean stop() {
        return true;
    }

    @Override
    public boolean save() {

        return true;
    }

    public static void reloadActivityData() {
        getLogger().info("reload SteleSoul begin");

        // 拿活动数据
        List<ActivityInfo> list = NormalActivityMgr.getOpenActivityInfoList(eActivityType.SteleSoul.getValue());
        if (list.isEmpty()) {
            steleSoulConfig = null;
            getLogger().info("reload SteleSoul finish, no activity in show time.");
            return;
        }
        ActivityInfo activityInfo = list.get(0);
        int activityId = activityInfo.getActivityId();

        Map<String, ActivityConfig> configMap = NormalActivityMgr.getActivityConfigMap(activityId);

        // 初始化活动配置
        SteleSoulConfig config = new SteleSoulConfig();
        config.setActivityInfo(activityInfo);
        config.initActivityConfig(configMap);
        config.setSteleSoulMapConfig(SteleSoulBusiness.getSteleSoulMapConfig(activityId));
        config.setSteleSoulPeriodConfig(SteleSoulBusiness.getSteleSoulPeriodConfig(activityId));
        config.setSteleSoulReviewConfigMap(SteleSoulBusiness.getSteleSoulReviewConfig(activityId));

        for (Map<Integer, SteleSoulMapConfig> map : config.getSteleSoulMapConfig().values()) {
            for(SteleSoulMapConfig mapConfig:map.values()) {
                mapConfig.init();
            }
        }

        setSteleSoulConfig(config);

        for (GamePlayer player : GamePlayerMgr.getAllOnlinePlayer()) {
            SteleSoulModule module = player.getModule(SteleSoulModule.class);
            module.syncConfig();
            module.initUserData();
            module.syncUserData();
        }
    }

    public static ActivityInfo getActivityInfo() {
        return steleSoulConfig == null ? null : steleSoulConfig.getActivityInfo();
    }

    public static SteleSoulConfig getSteleSoulConfig() {
        return steleSoulConfig;
    }

    public static void setSteleSoulConfig(SteleSoulConfig steleSoulConfig) {
        SteleSoulMgr.steleSoulConfig = steleSoulConfig;
    }

    /**
     * 注魂逻辑（抽奖）  无扣除、无发送奖励逻辑
     * @param userData 玩家数据
     * @param itemCount 道具数量
     */
    public static Property autoInsert(SteleSoulUserData userData, long itemCount) {
        // 数据
        SteleSoulConfig config = getSteleSoulConfig();
        Map<Integer, SteleSoulPeriodConfig> periodConfigMap = config.getSteleSoulPeriodConfig();
        Map<Integer, Map<Integer, SteleSoulMapConfig>> mapConfigMap = config.getSteleSoulMapConfig();
        Map<Integer, SteleSoulReviewConfig> reviewConfigMap = config.getSteleSoulReviewConfigMap();

        // 奖励
        Property award = new Property();

        // 当前层数
        int round = userData.getRound();
        int newRound = round + 1;
        // 依照当前层数，获取表格配置消耗层数
        int cfgRound = 0;
        int newCfgRound = 0;
        for (int l : periodConfigMap.keySet()) {
            if (round >= l && cfgRound <= l) {
                cfgRound = l;
            }
            // 这里是为了判断下一层更新了，阶段变化
            if (newRound >= l && newCfgRound <= l) {
                newCfgRound = l;
            }
        }

        SteleSoulPeriodConfig periodConfig = periodConfigMap.get(cfgRound);// 获取每次抽奖消耗及道具
        int consumeCount = periodConfig.getConsume();
        while (itemCount > consumeCount && consumeCount > 0){
            // 当前阶段
            int period = periodConfig.getId();
            // 当前圈数
            int circle = userData.getCircle();
            // 该圈格子列表
            Map<Integer, SteleSoulMapData> mapData = userData.getMapData();
            List<SteleSoulIndexData> awardList = mapData.get(circle).getSteleSoulIndexDataMsg();

            SteleSoulMapConfig mapConfig = mapConfigMap.get(period).get(circle + 1);
            // 奖励配置
            String reward = mapConfig.getReward();
            String surpriseReward = mapConfig.getSurpriseReward();
            int randomIndex = randomOneIndex(userData);
            if (randomIndex == -1){
                return award;
            }

            boolean isSurprise = awardList.get(randomIndex).getState() == eSteleSoulStateType.TYPE_SURPRISE.getType();
            if(isSurprise){
                // 如果抽到了彩蛋
                for (SteleSoulIndexData steleSoulIndexData:awardList) {
                    if (steleSoulIndexData.getState() == eSteleSoulStateType.TYPE_SURPRISE.getType()) {
                        // 记录彩蛋格子奖励
                        Property SurpriseProperty = PropertyHelper.parseNewStringToProperty(surpriseReward);
                        award.addProperty(SurpriseProperty);
                        steleSoulIndexData.setState(eSteleSoulStateType.TYPE_SURPRISE_AWARD.getType());
                        steleSoulIndexData.setReward(PropertyHelper.parsePropertyToString(SurpriseProperty));
                    } else if (steleSoulIndexData.getState() == eSteleSoulStateType.TYPE_NORMAL.getType()) {
                        // 记录普通格子奖励
                        Property property = PropertyHelper.parseNewStringToProperty(reward);
                        award.addProperty(property);
                        steleSoulIndexData.setState(eSteleSoulStateType.TYPE_NORMAL_TRIGGER_AWARD.getType());
                        steleSoulIndexData.setReward(PropertyHelper.parsePropertyToString(property));
                    }
                }
                break;
            } else {
                // 格子是普通格子
                // 把格子内容置为非0
                SteleSoulIndexData data = awardList.get(randomIndex);
                Property property = PropertyHelper.parseNewStringToProperty(reward);
                award.addProperty(property);
                data.setState(eSteleSoulStateType.TYPE_NORMAL_AWARD.getType());
                data.setReward(PropertyHelper.parsePropertyToString(property));
            }

            // 保底次数更新
            userData.setParamOne(userData.getParamOne() - 1);
            userData.setParamTwo(userData.getParamTwo() - 1);

            int awardIndexNum = 0;
            for (SteleSoulIndexData data : awardList) {
                if (isAward(data.getState())) {
                    awardIndexNum++;
                }
            }

            // 修改数据，当抽到彩蛋层或者整层抽完之后进入下一层
            if (isSurprise || awardIndexNum >= awardList.size()) {
                int maxCircle = config.getMapStructure().size();
                // 圈数已经最大，进入下一层
                if (circle + 1 >= maxCircle) {
                    // 判断是不是有大奖，有就发给他
                    if(reviewConfigMap.containsKey(circle)){
                        String reviewRewardList = reviewConfigMap.get(circle).getRewardList();
                        Property property = PropertyHelper.parseStringToProperty(reviewRewardList);
                        award.addProperty(property);
                    }
                    SteleSoulUserData newUserData = createUserData(userData.getUserId(), newRound, 0);
                    // 当前层数
                    round = newUserData.getRound();
                    userData.setRound(round);
                    userData.setCircle(newUserData.getCircle());
                    userData.setMapData(newUserData.getMapData());
                    userData.setParamOne(newUserData.getParamOne());
                    userData.setParamTwo(newUserData.getParamTwo());
                    newRound = round + 1;
                    // 如果升层则重新判断阶段，重新判断消耗
                    for (int l : periodConfigMap.keySet()) {
                        if (round >= l && cfgRound <= l) {
                            cfgRound = l;
                        }
                        // 这里是为了判断下一层更新了，阶段变化
                        if (newRound >= l && newCfgRound <= l) {
                            newCfgRound = l;
                        }
                    }
                    periodConfig = periodConfigMap.get(cfgRound);// 获取每次抽奖消耗及道具
                    consumeCount = periodConfig.getConsume();
                } else {
                    userData.setCircle(circle + 1);
                    SteleSoulParamData steleSoulParamData = randomParam(period, circle + 1);
                    userData.setParamOne(steleSoulParamData.getParamOne());
                    userData.setParamTwo(steleSoulParamData.getParamTwo());
                }
            }
            itemCount -= consumeCount;
        }

        return award;
    }

    // 判状态是否已领取
    public static boolean isAward(int Type){
        return Type == eSteleSoulStateType.TYPE_NORMAL_AWARD.getType() || Type == eSteleSoulStateType.TYPE_SURPRISE_AWARD.getType() || Type == eSteleSoulStateType.TYPE_NORMAL_TRIGGER_AWARD.getType();
    }

    /**
     * 依照阶段 + 圈数构造一份新数据
     */
    public static SteleSoulUserData createUserData(long userId, int round, int circle) {
        SteleSoulConfig config = SteleSoulMgr.getSteleSoulConfig();
        Map<Integer, SteleSoulPeriodConfig> periodConfigMap = config.getSteleSoulPeriodConfig();
        Map<Integer, Map<Integer, SteleSoulMapConfig>> mapConfigMap = config.getSteleSoulMapConfig();

        // 依照当前层数，获取表格配置消耗层数
        int cfgRound = 0;
        for (int l : periodConfigMap.keySet()) {
            if (round >= l && cfgRound <= l) {
                cfgRound = l;
            }
        }
        SteleSoulPeriodConfig periodConfig = periodConfigMap.get(cfgRound);
        // 当前阶段
        int period = periodConfig.getId();

        // 默认设置
        SteleSoulUserData userData = new SteleSoulUserData();
        userData.setActivityId(config.getActivityInfo().getActivityId());
        userData.setUserId(userId);
        userData.setRound(round);
        userData.setCircle(circle);
        // 一圈一圈的构造格子
        Map<Integer, SteleSoulMapData> newMapData = new HashMap<>();
        List<Integer> mapStructure = config.getMapStructure();
        for (int i = 0; i < mapStructure.size(); i++) {
            SteleSoulMapData steleSoulMapData = new SteleSoulMapData();
            // 随机彩蛋位置
            int indexNum = mapStructure.get(i);
            Map<Integer, SteleSoulMapConfig> checkMap = mapConfigMap.get(period);
            // 这里是因为从最外圈开始构造，如果最外圈没有，则设置当前圈为下一个内圈
            List<SteleSoulIndexData> steleSoulIndexDataList = new ArrayList<>();
            if(!checkMap.containsKey(i + 1)){
                userData.setCircle(i + 1);
            } else {
                SteleSoulMapConfig mapConfig = mapConfigMap.get(period).get(i + 1);
                List<Integer> surpriseIndexL = RandomHelper.getDifferentRandomNum(indexNum, mapConfig.getSurprisePlaid());
                for (int j = 0; j < indexNum; j++) {
                    SteleSoulIndexData steleSoulIndexData = new SteleSoulIndexData();
                    if (surpriseIndexL.contains(j)) {
                        // 设置成彩蛋格子
                        steleSoulIndexData.setState(eSteleSoulStateType.TYPE_SURPRISE.getType());
                    } else {
                        steleSoulIndexData.setState(eSteleSoulStateType.TYPE_NORMAL.getType());
                    }
                    steleSoulIndexDataList.add(j, steleSoulIndexData);
                }
            }
            steleSoulMapData.setSteleSoulIndexDataMsg(steleSoulIndexDataList);
            newMapData.put(i, steleSoulMapData);
        }
        userData.setMapData(newMapData);

        // 随机出彩蛋次数
        SteleSoulParamData steleSoulParamData = SteleSoulMgr.randomParam(period, userData.getCircle());
        userData.setParamOne(steleSoulParamData.getParamOne());
        userData.setParamTwo(steleSoulParamData.getParamTwo());
        userData.setLastIndex("");

        return userData;
    }

    /**
     * 随机保底数
     *
     * @param period 阶段
     * @param circle 圈数
     * @return SteleSoulParamData 保底次数
     */
    public static SteleSoulParamData randomParam(int period, int circle) {
        SteleSoulParamData steleSoulParamData = new SteleSoulParamData();

        SteleSoulConfig config = getSteleSoulConfig();
        SteleSoulMapConfig mapConfig = config.getSteleSoulMapConfig().get(period).get(circle + 1);
        int surpriseNum = mapConfig.getSurprisePlaid();
        List<Integer> mapStructure = config.getMapStructure();
        int listLength = mapStructure.get(circle);
        Random random = new Random();
        // 随机出保底次数
        int paramOneFirstOne = mapConfig.getParamOneList().get(0);
        int paramOneSecondOne = mapConfig.getParamOneList().get(1);
        int paramTwoFirstOne = mapConfig.getParamTwoList().get(0);
        int paramTwoSecondOne = mapConfig.getParamTwoList().get(1);
        int paramTwo = listLength - surpriseNum;
        // 随机最低次数
        if(paramOneSecondOne != 0 && paramOneSecondOne == paramOneFirstOne){
            steleSoulParamData.setParamOne(paramOneSecondOne);
        } else if (paramOneSecondOne != 0 && paramOneSecondOne > paramOneFirstOne){
            int paramOne = random.nextInt(paramOneSecondOne - paramOneFirstOne) + paramOneFirstOne;
            steleSoulParamData.setParamOne(paramOne);
        }

        if(paramTwoSecondOne != 0 && paramTwoSecondOne == paramTwoFirstOne){
            paramTwo = paramTwoSecondOne;
        } else if (paramTwoSecondOne != 0 && paramTwoSecondOne > paramTwoFirstOne) {
            // 如果参数没填，或者随机出的数大于该行的长度 - 彩蛋数则赋值为长度 - 彩蛋数
            if (paramTwo < listLength) {
                paramTwo = random.nextInt(paramTwoSecondOne - paramTwoFirstOne) + paramTwoFirstOne;
            }
        }
        steleSoulParamData.setParamTwo(paramTwo);

        return steleSoulParamData;
    }

    public static int randomOneIndex(SteleSoulUserData userData){
        Random random = new Random();

        // 取得无法抽中的前N次
        int lessTime = userData.getParamOne();
        int circle = userData.getCircle();
        // 该圈格子列表
        Map<Integer, SteleSoulMapData> mapData = userData.getMapData();
        List<SteleSoulIndexData> awardList = mapData.get(circle).getSteleSoulIndexDataMsg();
        // 计算还剩几个格子
        int leftIndexNum = 0;
        // 计算场上的彩蛋格子数量（格子数量是由表格配置随机的，这里写法是为了方便修改数据）
        int surprisePlaid = 0;
        for (SteleSoulIndexData data : awardList) {
            if (!isAward(data.getState())) {
                leftIndexNum++;
            }
            // 不需要判断已抽到，因为抽到就下一圈了
            if (data.getState() == eSteleSoulStateType.TYPE_SURPRISE.getType()) {
                surprisePlaid++;
            }
        }

        if (surprisePlaid > 0 && userData.getParamTwo() < 1) {
            // 1.满足保底次数，随机一个彩蛋格子
            int surpriseIndex = random.nextInt(surprisePlaid);
            for (int i = 0; i < awardList.size(); i++) {
                // 返回抽到彩蛋的位置
                if (awardList.get(i).getState() == eSteleSoulStateType.TYPE_SURPRISE.getType() && surpriseIndex == 0) {
                    return i;
                } else if (awardList.get(i).getState() == eSteleSoulStateType.TYPE_SURPRISE.getType()) {
                    surpriseIndex--;
                }
            }
        } else if (surprisePlaid > 0 && 1 > lessTime){
            // 2.满足抽中彩蛋最低次数，随机所有未抽格子
            int randomInt = random.nextInt(leftIndexNum);
            for (int i = 0; i < awardList.size(); i++) {
                SteleSoulIndexData data = awardList.get(i);
                if (!isAward(data.getState()) && randomInt == 0) {
                    return i;
                } else if (!isAward(data.getState())) {
                    randomInt--;
                }
            }
        } else {
            // 3.不满足抽中彩蛋最低次数，仅在未抽普通格子中随机
            if (leftIndexNum <= surprisePlaid) {//到这里就异常了
                getLogger().error("userId={} leftIndexNum <= surprisePlaid, leftIndexNum:{}, surprisePlaid:{}", userData.getUserId(), leftIndexNum, surprisePlaid);
                for (int i = 0; i < awardList.size(); i++) {
                    // 返回抽到彩蛋的位置
                    if (awardList.get(i).getState() == eSteleSoulStateType.TYPE_SURPRISE.getType()) {
                        return i;
                    }
                }
                return -1;
            }
            int randomNormalIndex = random.nextInt(leftIndexNum - surprisePlaid);
            for (int i = 0; i < awardList.size(); i++) {
                SteleSoulIndexData data = awardList.get(i);
                if (data.getState() == eSteleSoulStateType.TYPE_NORMAL.getType() && randomNormalIndex == 0) {
                    return i;
                } else if (data.getState() == 0) {
                    randomNormalIndex--;
                }
            }
        }
        return -1;
    }

}
